package iSOCK::Controller::Login;

use Catalyst qw( Authentication );
use DateTime;
use SOCK::BOT qw( last_breath );
use Try::Tiny;

use Moose;
use namespace::autoclean;

BEGIN { extends 'iSOCK::Controller::Root' }

=head1 NAME

iSOCK::Controller::Login - Login Controller for iSOCK

=head1 DESCRIPTION

[enter your description here]

=head1 METHODS

=cut

sub _normalize : Private {
  my ( $string ) = @_;
  
  $string =~ s/^\s+//;
  $string =~ s/\s+$//;
  
  $string =~ s/\s+/ /g;
  
  return $string;
}

sub _pretty : Private {
  my ( $name ) = @_;
  
  $name =~ s/ \b (\w+) \b / ucfirst ( lc $1 ) /exg;
  
  return $name;
}

sub index :Path :Args(0) {
  my ( $self, $c ) = @_;

  if ( $c->request->method eq 'POST' && $c->request->parameters->{form_login_submit} ) {
    my ( $login, $password ) = map { $c->request->parameters->{$_} } qw( user password );
    
    my $authenticated = $c->authenticate ( { username => $login, password => $password } => 'ldap' );

    my $user_m = $c->model ( 'App::User' );
    my $user_r = $user_m->find ( $authenticated ? $c->user->id : $login );
    
    if ( $authenticated && $user_r && ( $c->user->id ne $login ) ) {
      $c->stash->{action_failed} = "Wrong user ID, use " . $c->user->id . " instead!";
    }
    else {
      if ( $authenticated && !$user_r ) {
        $c->log->debug ( "[Controller::Login::index] Authenticated via LDAP." );

        my $ldap_id = $c->user->id;

        try {
          $user_r = $user_m->create ({
            id       =>           _normalize ( $ldap_id                                                         ),
            name     => _pretty ( _normalize ( $c->user->cn                                                     ) ),
            mail     =>           _normalize ( $c->user->mail                                                   ),
            location =>           _normalize ( $c->user->ldap_entry->get_value ( 'physicalDeliveryOfficeName' ) ),
          });
        }
        catch {
          my $last_breath = last_breath ( $_ );
          
          $c->log->error ( "[Controller::Login::index] Caught an exception (\"$last_breath\")!" );
          
          $c->stash->{action_failed} = $last_breath;
        };

        if ( $user_r ) {
          $c->log->debug ( "[Controller::Login::index] Created '$ldap_id' user." );
          
          if ( $c->user->id ne $login ) {
            $c->stash->{action_questionable} = "Account created with \"$ldap_id\" corpo login (you keyed \"$login\" instead).";
          }
          else {
            $c->stash->{action_succeeded}    = "Account created.";
          }
        }
        else {
          $c->log->error ( "[Controller::Login::index] Could not create any user for '$login' login!" );
        }
      }
      elsif ( !$authenticated && $user_r && $user_r->password ) {
        $authenticated = $c->authenticate ( { id => $login, password => $password } => 'db' );
        
        if ( $authenticated ) {
          $c->log->debug ( "[Controller::Login::index] Authenticated via DB." );
        }
        else {
          $c->log->error ( "[Controller::Login::index] Not authenticated via DB." );
        }
      }

      if ( $user_r && $authenticated ) {
        $self->session_path ( $c );

        my $session_id = $c->sessionid;
        my $now        = DateTime->now;

        $user_r->update ({ session_id => $session_id, last_login => $now });
        $c->model ( 'App' )->alter_session ({ c => $c, user_r => $user_r, session_id => $session_id, last_access => $now });

        for my $session_r ( grep { $_->id ne $session_id && !$_->restful && !$_->busy } $user_r->sessions ) {
          $c->log->info ( "[Controller::Login::index] Reaping " . $session_r->id . " session..." );

          system "rm -rf " . $c->config->{directory}->{tmp} . '/' . $session_r->id;
          $session_r->delete;

          $c->log->info ( "Done." );
        }

        $c->log->debug ( "[Controller::Login::index] Succeeded." );

       #$c->flash->{action_succeeded} = "Welcome, " . $user_r->name . "!";

        $c->response->redirect ( $c->request->parameters->{pre_login_uri} || $c->uri_for ( $user_r->login_uri || $c->config->{default_path} ) );
        $c->detach;
      }
      else {
        $c->log->error ( "[Controller::Login::index] Failed!" );

        $c->stash->{action_failed} ||= "Wrong user or password!";
      }
    }
  }
  
  if ( my $uri = $c->stash->{pre_login_uri} ) {
    $c->flash->{pre_login_uri} = $uri;
  }
  
  $c->forward ( qw( iSOCK::Controller::Root render_view ) );
}

=head1 AUTHOR

Xavier Caron

=head1 LICENSE

This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
